bitkeeper revision 1.1159.187.4 (41a471c8NjyQJy-vepqpb8H7LdzHzA)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Wed, 24 Nov 2004 11:34:32 +0000 (11:34 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Wed, 24 Nov 2004 11:34:32 +0000 (11:34 +0000)
Allow preemption of long-running hypercalls for softirq processing.

xen/arch/x86/domain.c
xen/arch/x86/memory.c
xen/arch/x86/traps.c
xen/arch/x86/x86_32/entry.S
xen/common/dom_mem_ops.c
xen/common/grant_table.c
xen/include/xen/irq_cpustat.h
xen/include/xen/sched.h

index 69e1506a02d1ba0a45f93114924ca210742cfde2..77a39a2a9752b1256e3918da4341788b05302e5d 100644 (file)
@@ -426,6 +426,22 @@ long do_iopl(domid_t domain, unsigned int new_io_pl)
     return 0;
 }
 
+void hypercall_create_continuation(unsigned int op, unsigned int nr_args, ...)
+{
+    execution_context_t *ec = get_execution_context();
+    unsigned long *preg = &ec->ebx;
+    unsigned int i;
+    va_list args;
+
+    ec->eax  = op;
+    ec->eip -= 2;  /* re-execute 'int 0x82' */
+
+    va_start(args, nr_args);
+    for ( i = 0; i < nr_args; i++ )
+        *preg++ = va_arg(args, unsigned long);
+    va_end(args);
+}
+
 #endif
 
 
index 0a15601bf4e0db89e4bed2f3ecf5a246060abfe3..c6d9951bc56399ae06546ca426de2b8a1c84f331 100644 (file)
@@ -1300,6 +1300,9 @@ int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count)
 
     for ( i = 0; i < count; i++ )
     {
+        hypercall_may_preempt(
+            __HYPERVISOR_mmu_update, 3, ureqs, count-i, success_count);
+
         if ( unlikely(__copy_from_user(&req, ureqs, sizeof(req)) != 0) )
         {
             MEM_LOG("Bad __copy_from_user");
@@ -1455,7 +1458,7 @@ int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count)
     }
 
     if ( unlikely(success_count != NULL) )
-        put_user(count, success_count);
+        put_user(i, success_count);
 
     return rc;
 }
index f5fb6618d301ce9de2ae1556099b61c9d19770e0..3a8f8cdd1568f45b6c058aeb74bdddb9e7a2238f 100644 (file)
@@ -804,6 +804,8 @@ long do_set_trap_table(trap_info_t *traps)
 
     for ( ; ; )
     {
+        hypercall_may_preempt(__HYPERVISOR_set_trap_table, 1, traps);
+
         if ( copy_from_user(&cur, traps, sizeof(cur)) ) return -EFAULT;
 
         if ( cur.address == 0 ) break;
index 6b6376e8bcd600d7e1686c98e9a7939f6cbec886..c92090a1413ee374ebded806e69bdb499d74fa15 100644 (file)
@@ -95,6 +95,11 @@ do_multicall:
         jnc   bad_multicall_address
 multicall_loop:
         pushl %ecx
+        movl  4(%esp),%ecx               # %ecx = struct domain
+        movl  DOMAIN_processor(%ecx),%eax
+        shl   $6,%eax                    # sizeof(irq_cpustat) == 64
+        testl $~0,SYMBOL_NAME(irq_stat)(%eax,1)
+        jnz   multicall_preempt
 multicall_fault1: 
         pushl 20(%ebx)      # args[4]
 multicall_fault2: 
@@ -120,6 +125,17 @@ multicall_fault7:
         xorl  %eax,%eax
         jmp   ret_from_hypercall
 
+multicall_preempt:
+        # NB. remaining nr_calls is already at top of stack
+        pushl %ebx                             # call_list
+        pushl $2                               # nr_args == 2
+        pushl $__HYPERVISOR_multicall          # op == __HYPERVISOR_multicall
+        call  hypercall_create_continuation
+        addl  $16,%esp
+        popl  %ebx
+        movl  $__HYPERVISOR_multicall,%eax        
+        jmp   ret_from_hypercall
+        
 bad_multicall_address:
         popl  %ebx
         movl  $-EFAULT,%eax
index 2169fad2a184a916b399e009f6f5e137df27ccdb..8e9a9e97e18212c34671b433ae78662765f21bf8 100644 (file)
@@ -35,6 +35,12 @@ static long alloc_dom_mem(struct domain *d,
 
     for ( i = 0; i < nr_extents; i++ )
     {
+        hypercall_may_preempt(
+            __HYPERVISOR_dom_mem_op, 5,
+            MEMOP_increase_reservation,
+            &extent_list[i], nr_extents-i, extent_order,
+            (d == current) ? DOMID_SELF : d->id);
+
         if ( unlikely((page = alloc_domheap_pages(d, extent_order)) == NULL) )
         {
             DPRINTK("Could not allocate a frame\n");
@@ -63,6 +69,12 @@ static long free_dom_mem(struct domain *d,
 
     for ( i = 0; i < nr_extents; i++ )
     {
+        hypercall_may_preempt(
+            __HYPERVISOR_dom_mem_op, 5,
+            MEMOP_decrease_reservation,
+            &extent_list[i], nr_extents-i, extent_order,
+            (d == current) ? DOMID_SELF : d->id);
+
         if ( unlikely(__get_user(mpfn, &extent_list[i]) != 0) )
             return i;
 
index 2c948b743371cd051cfe921aeb63298886f5013e..e01cad9e80304ea67f58d40b86aea59753c16fec 100644 (file)
@@ -437,6 +437,9 @@ do_grant_table_op(
 {
     long rc;
 
+    /* XXX stubbed out XXX */
+    return -ENOSYS;
+
     if ( count > 512 )
         return -EINVAL;
 
index 075f55bf297c349e9327f72678de408900f22a48..9d09ad3fb88fd4c26eab81c707b7d0087748ec65 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <xen/config.h>
+#include <asm/hardirq.h>
 
 /*
  * Simple wrappers reducing source bloat.  Define all irq_stat fields
@@ -17,7 +18,7 @@
  * definitions instead of differing sets for each arch.
  */
 
-extern irq_cpustat_t irq_stat[];                       /* defined in asm/hardirq.h */
+extern irq_cpustat_t irq_stat[];
 
 #ifdef CONFIG_SMP
 #define __IRQ_STAT(cpu, member)        (irq_stat[cpu].member)
index 970a27c56b590cbb2cda00b2afd08f09087ba84b..a67547e6b93952620e1e55278345e6d2aab423d7 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/current.h>
 #include <xen/spinlock.h>
 #include <xen/grant_table.h>
+#include <xen/irq_cpustat.h>
 
 extern unsigned long volatile jiffies;
 extern rwlock_t domlist_lock;
@@ -217,6 +218,14 @@ void continue_cpu_idle_loop(void);
 
 void continue_nonidle_task(void);
 
+void hypercall_create_continuation(unsigned int op, unsigned int nr_args, ...);
+#define hypercall_may_preempt(_op, _nr_args, _args...)               \
+    do {                                                             \
+        if ( unlikely(softirq_pending(smp_processor_id())) ) {       \
+            hypercall_create_continuation(_op , _nr_args , ##_args); \
+            return _op;                                              \
+    } } while ( 0 )
+
 /* This domain_hash and domain_list are protected by the domlist_lock. */
 #define DOMAIN_HASH_SIZE 256
 #define DOMAIN_HASH(_id) ((int)(_id)&(DOMAIN_HASH_SIZE-1))